# !/usr/bin/env python
# -*-coding:utf-8 -*-
"""
# File       : api_utils.py
# Time       ：2023/1/29 22:24
# Author     ：Y-aong
# version    ：python 3.7
# Description：orderlines util
"""
import inspect
import json
from typing import List, Any, Union

from apis.orderlines.models import TaskInstance
from apis.orderlines.schema.task_schema import TaskInstanceLogSchema, TaskInstanceSchema
from public.base_model import session_scope
from public.logger import logger
from public.utils.const import DEFAULT_CONFIG


class CustomEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, bytes):
            return str(obj, encoding='utf-8')
        return json.JSONEncoder.default(self, obj)


def get_current_node(task_id: str, task_nodes: List[dict]) -> dict:
    """
    根据任务id获取当前运行的任务
    Obtain the currently running task based on the task id
    """
    for node in task_nodes:
        if node.get('task_id') == task_id:
            return node
    raise AttributeError(f'use task id {task_id} The task node can not find')


def get_variable_value(variable_value: Any, variable_type: str) -> Any:
    """按类型获取变量值. get variable value by type"""
    if not variable_value:
        return None
    if variable_type == 'int':
        return int(variable_value)
    elif variable_type == 'str':
        return str(variable_value)
    elif variable_type == 'float':
        return float(variable_value)
    elif variable_type == 'bool':
        return bool(variable_value)
    elif variable_type == 'json':
        return json.dumps(variable_value)
    elif variable_type in 'dict':
        return json.loads(variable_value)
    else:
        return None


def get_method_param_annotation(method) -> tuple:
    """
    获取方法的参数类型注解
    Gets the parameter type annotation for the method
    @param method: method
    @return: flag, param_annotation
    flag is use pydantic
    """
    sig = inspect.signature(method)
    parameters = sig.parameters
    arg_keys = tuple(arg for arg in parameters.keys() if arg != 'self')
    if len(arg_keys) == 1:
        for arg_name in arg_keys:
            return True, parameters[arg_name].annotation
    return False, tuple(parameters.get(arg) for arg in parameters.keys() if arg != 'self')


def default_task_config(task_config: List[dict]):
    """默认任务配置"""
    if task_config is None:
        task_config = DEFAULT_CONFIG

    _task_config = {}
    if isinstance(task_config, str):
        task_config = json.loads(task_config)
    for item in task_config:
        if isinstance(item, dict):
            _task_config[item.get('config_name')] = item.get('config_value')
    return _task_config


def clear_all_db(process_id=None):
    """clear db only test"""
    from apis.orderlines.models import Process, ProcessInstance, Task, TaskInstance, Variable
    from apis.orderlines.models import VariableInstance
    with session_scope() as session:
        if process_id:
            session.query(TaskInstance).filter(TaskInstance.process_id == process_id).delete()
            session.query(Task).filter(Task.process_id == process_id).delete()
            session.query(ProcessInstance).filter(ProcessInstance.process_id == process_id).delete()
            session.query(Process).filter(Process.process_id == process_id).delete()
            session.query(Variable).filter(Variable.process_id == process_id).delete()
            session.query(VariableInstance).filter(VariableInstance.process_id == process_id).delete()
        else:
            session.query(TaskInstance).delete()
            session.query(Task).delete()
            session.query(ProcessInstance).delete()
            session.query(Process).delete()
            session.query(Variable).delete()
            session.query(VariableInstance).delete()
        session.commit()


def get_task_config_item(task_config: Union[list, dict], item_name: str, default=None):
    """获取任务配置"""
    if isinstance(task_config, dict):
        return task_config.get(item_name) or default
    if isinstance(task_config, list):
        for config in task_config:
            if config.get('config_name') == item_name:
                return config.get('config_value')
    return default


def get_task_instance(task_instance_id, is_logger=True):
    """获取任务实例"""
    with session_scope() as session:
        obj = session.query(TaskInstance).filter(TaskInstance.task_instance_id == task_instance_id).first()
        if obj is None:
            logger.error(f'获取到的任务实例obj::{obj}')
            raise ValueError(f'task_instance_id::{task_instance_id} can not find obj')
        if is_logger:
            return TaskInstanceLogSchema().dump(obj)
        else:
            return TaskInstanceSchema().dump(obj)
